home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / tex / cawf404.zip / pass2.c < prev    next >
C/C++ Source or Header  |  1993-12-07  |  21KB  |  844 lines

  1. /*
  2.  *    pass2.c - cawf(1) pass 2 function
  3.  */
  4.  
  5. /*
  6.  *    Copyright (c) 1991 Purdue University Research Foundation,
  7.  *    West Lafayette, Indiana 47907.  All rights reserved.
  8.  *
  9.  *    Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
  10.  *    University Computing Center.  Not derived from licensed software;
  11.  *    derived from awf(1) by Henry Spencer of the University of Toronto.
  12.  *
  13.  *    Permission is granted to anyone to use this software for any
  14.  *    purpose on any computer system, and to alter it and redistribute
  15.  *    it freely, subject to the following restrictions:
  16.  *
  17.  *    1. The author is not responsible for any consequences of use of
  18.  *       this software, even if they arise from flaws in it.
  19.  *
  20.  *    2. The origin of this software must not be misrepresented, either
  21.  *       by explicit claim or by omission.  Credits must appear in the
  22.  *       documentation.
  23.  *
  24.  *    3. Altered versions must be plainly marked as such, and must not
  25.  *       be misrepresented as being the original software.  Credits must
  26.  *       appear in the documentation.
  27.  *
  28.  *    4. This notice may not be removed or altered.
  29.  */
  30.  
  31. #include "cawf.h"
  32. #include <ctype.h>
  33.  
  34. /*
  35.  * Pass2(line) - process the nroff requests in a line and break
  36.  *         text into words for pass 3
  37.  */
  38.  
  39. void
  40. Pass2(line)
  41.     unsigned char *line;
  42. {
  43.     int brk;            /* request break status */
  44.     unsigned char buf[MAXLINE];    /* working buffer */
  45.     unsigned char c;        /* character buffer */
  46.     double d;            /* temporary double */
  47.     double exscale;            /* expression scaling factor */
  48.     double expr[MAXEXP];            /* expressions */
  49.     unsigned char exsign[MAXEXP];    /* expression signs */
  50.     int i, j;            /* temporary indexes */
  51.     int inword;            /* word processing status */
  52.     int nexpr;            /* number of expressions */
  53.     unsigned char nm[4], nm1[4];    /* names */
  54.     int nsp;            /* number of spaces */
  55.     unsigned char op;        /* expression term operator */
  56.     unsigned char opstack[MAXSP];    /* expression operation stack */
  57.     unsigned char period;        /* end of word status */
  58.     unsigned char *s1, *s2, *s3;    /* temporary string pointers */
  59.     double sexpr[MAXEXP];           /* signed expressions */
  60.     int sp;                /* expression stack pointer */
  61.     unsigned char ssign;        /* expression's starting sign */
  62.     double tscale;            /* term scaling factor */
  63.     double tval;            /* term value */
  64.     double val;            /* term value */
  65.     double valstack[MAXSP];        /* expression value stack */
  66.     unsigned char xbuf[MAXLINE];    /* expansion buffer */
  67.  
  68.     if (line == NULL) {
  69.     /*
  70.      * End of macro expansion.
  71.      */
  72.         Pass3(DOBREAK, (unsigned char *)"need", 4, NULL, 999);
  73.         return;
  74.     }
  75.     /*
  76.      * Adjust line number.
  77.      */
  78.     if (Lockil == 0)
  79.         P2il++;
  80.     /*
  81.      * Empty line - "^[ \t]*$" or "^\\\"".
  82.      */
  83.     if (regexec(Pat[6].pat, line)
  84.     ||  strncmp((char *)line, "\\\"", 2) == 0) {
  85.         Pass3(DOBREAK, (unsigned char *)"space", 5, NULL, 0);
  86.         return;
  87.     }
  88.     /*
  89.      * Line begins with white space.
  90.      */
  91.     if (*line == ' ' || *line == '\t') {
  92.         Pass3(DOBREAK, (unsigned char *)"flush", 5, NULL, 0);
  93.         Pass3(0, (unsigned char *)"", 0, NULL, 0);
  94.     }
  95.     if (*line != '.' && *line != '\'') {
  96.     /*
  97.      * Line contains text (not an nroff request).
  98.      */
  99.         if (Font[0] == 'R' && Backc == 0 && Aftnxt == NULL
  100.         &&  regexec(Pat[7].pat, line) == 0) {
  101.             /*
  102.              * The font is Roman, there is no "\\c" or "after next"
  103.              * trap pending and and the line has no '\\', '\t', '-',
  104.              * or "  "  (regular expression "\\|\t|-|  ").
  105.              *
  106.              * Output each word of the line as "<length> <word>".
  107.              */
  108.             for (s1 = line;;) {
  109.                 while (*s1 && *s1 == ' ')
  110.                     s1++;
  111.                 if (*s1 == '\0')
  112.                     break;
  113.                 for (s2 = s1, s3 = buf; *s2 && *s2 != ' ';)
  114.                     *s3++ = Trtbl[(int)*s2++];
  115.                 *s3 = '\0';
  116.                 Pass3((s2 - s1), buf, (s2 - s1), NULL, 0);
  117.                 s1 = *s2 ? ++s2 : s2;
  118.             }
  119.             /*
  120.              * Line terminates with punctuation and optional
  121.              * bracketing (regular expression "[.!?:][\])'\"*]*$").
  122.              */
  123.             if (regexec(Pat[8].pat, line))
  124.                 Pass3(NOBREAK, (unsigned char *)"gap", 3,
  125.                     NULL, 2);
  126.             if (Centering > 0) {
  127.                 Pass3(DOBREAK,(unsigned char *)"center", 6,
  128.                     NULL, 0);
  129.                 Centering--;
  130.             } else if (Fill == 0)
  131.                 Pass3(DOBREAK, (unsigned char *)"flush", 5,
  132.                     NULL, 0);
  133.             return;
  134.         }
  135.         /*
  136.          * Line must be scanned a character at a time.
  137.          */
  138.         inword = nsp = 0;
  139.         period = '\0';
  140.         for (s1 = line;; s1++) {
  141.             /*
  142.              * Space or TAB causes state transition.
  143.              */
  144.             if (*s1 == '\0' || *s1 == ' ' || *s1 == '\t') {
  145.                 if (inword) {
  146.                     if (!Backc) {
  147.                         Endword();
  148.                         Pass3(Wordl, Word, Wordx,
  149.                             NULL, 0);
  150.                         if (Uhyph) {
  151.                           Pass3(NOBREAK,
  152.                             (unsigned char *)"nohyphen",
  153.                             8, NULL, 0);
  154.                         }
  155.                     }
  156.                     inword = 0;
  157.                     nsp = 0;
  158.                 }
  159.                 if (*s1 == '\0')
  160.                     break;
  161.             } else {
  162.                 if (inword == 0) {
  163.                     if (Backc == 0) {
  164.                         Wordl = Wordx = 0;
  165.                         Uhyph = 0;
  166.                     }
  167.                     Backc = 0;
  168.                     inword = 1;
  169.                     if (nsp > 1) {
  170.                         Pass3(NOBREAK,
  171.                             (unsigned char *)"gap",
  172.                             3, NULL, nsp);
  173.                     }
  174.                 }
  175.             }
  176.             /*
  177.              * Process a character.
  178.              */
  179.             switch (*s1) {
  180.             /*
  181.              * Space
  182.              */
  183.                  case ' ':
  184.                 nsp++;
  185.                 period = '\0';
  186.                 break;
  187.             /*
  188.              * TAB
  189.              */
  190.                  case '\t':
  191.                 Pass3(NOBREAK, (unsigned char *)"tabto", 5,
  192.                     NULL, 0);
  193.                 nsp = 0;
  194.                 period = '\0';
  195.                 break;
  196.             /*
  197.              * Hyphen if word is being assembled
  198.              */
  199.             case '-':
  200.                 if (Wordl <= 0
  201.                 || (Wordl == 1 && Word[Wordx - 1] == '-'))
  202.                     goto ordinary_char;
  203.                 if ((i = Findhy(NULL, 0, 0)) < 0) {
  204.                     Error(WARN, LINE, " no hyphen for font ",
  205.                     (char *)Font);
  206.                     return;
  207.                 }
  208.                 Endword();
  209.                 Pass3(Wordl, Word, Wordx, NULL, Hychar[i].len);
  210.                 Pass3(NOBREAK, (unsigned char *)"userhyphen",
  211.                     10, Hychar[i].str, Hychar[i].len);
  212.                 Wordl = Wordx = 0;
  213.                 period = '\0';
  214.                 Uhyph = 1;
  215.                 break;
  216.             /*
  217.              * Backslash
  218.              */
  219.             case '\\':
  220.                 s1++;
  221.                 switch(*s1) {
  222.                 /*
  223.                  * Comment - "\\\""
  224.                  */
  225.                 case '"':
  226.                     while (*(s1+1))
  227.                         s1++;
  228.                     break;
  229.                 /*
  230.                  * Change font - "\\fN"
  231.                  */
  232.                 case 'f':
  233.                     s1 = Asmcode(&s1, nm);
  234.                     if (nm[0] == 'P') {
  235.                         Font[0] = Prevfont;
  236.                         break;
  237.                     }
  238.                     for (i = 0; Fcode[i].nm; i++) {
  239.                         if (Fcode[i].nm == nm[0])
  240.                         break;
  241.                     }
  242.                     if (Fcode[i].nm == '\0'
  243.                     ||  nm[1] != '\0') {
  244.                         Error(WARN, LINE, " unknown font ",
  245.                             (char *)nm);
  246.                         break;
  247.                     }
  248.                     if (Fcode[i].status != '1') {
  249.                         Error(WARN, LINE,
  250.                         " font undefined ", (char *)nm);
  251.                         break;
  252.                     } else {
  253.                         Prevfont = Font[0];
  254.                         Font[0] = nm[0];
  255.                     }
  256.                     break;
  257.                 /*
  258.                  * Positive horizontal motion - "\\h\\n(NN" or
  259.                  * "\\h\\nN"
  260.                  */
  261.                 case 'h':
  262.                     if (s1[1] != '\\' || s1[2] != 'n') {
  263.                         Error(WARN, LINE,
  264.                         " no \\n after \\h", NULL);
  265.                         break;
  266.                     }
  267.                     s1 +=2;
  268.                     s1 = Asmcode(&s1, nm);
  269.                     if ((i = Findnum(nm, 0, 0)) < 0)
  270.                         goto unknown_num;
  271.                     if ((j = Numb[i].val) < 0) {
  272.                         Error(WARN, LINE, " \\h < 0 ",
  273.                         NULL);
  274.                         break;
  275.                     }
  276.                     if (j == 0)
  277.                         break;
  278.                     if ((strlen((char *)s1+1) + j + 1)
  279.                     >=  MAXLINE)
  280.                         goto line_too_long;
  281.                     for (s2 = &xbuf[1]; j; j--)
  282.                         *s2++ = ' ';
  283.                     (void) strcpy((char *)s2, (char *)s1+1);
  284.                     s1 = xbuf;
  285.                     break;
  286.                 /*
  287.                  * Save current position in register if "\\k<reg>"
  288.                  */
  289.                     case 'k':
  290.                     s1 = Asmcode(&s1, nm);
  291.                     if ((i = Findnum(nm, 0, 0)) < 0)
  292.                         i = Findnum(nm, 0, 1);
  293.                     Numb[i].val =
  294.                         (int)((double)Outll * Scalen);
  295.                     break;
  296.                 /*
  297.                  * Interpolate number - "\\n(NN" or "\\nN"
  298.                  */
  299.                 case 'n':
  300.                     s1 = Asmcode(&s1, nm);
  301.                     if ((i = Findnum(nm, 0, 0)) < 0) {
  302. unknown_num:
  303.                         Error(WARN, LINE,
  304.                             " unknown number register ",
  305.                         (char *)nm);
  306.                         break;
  307.                     }
  308.                     (void) sprintf((char *)buf, "%d"